/**
 * @file bull_hal_drv_wifi.c
 * @brief 
 * @author yejing (yejh@gongniu.cn)
 * @version 1.0
 * @date 2024-05-09
 * 
 * Copyright 2021-2023 GongNiu Inc. All Rights Reserved.
 * 
 */

#include "bull_hal_drv_wifi.h"
#include "bull_hal_sys_thread.h"
#include "bull_hal_sys_memory.h"
#include "bull_hal_sys_system.h"

#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "esp_system.h"
#include "esp_netif.h"
#include "esp_wifi_types.h"
#include "nvs_flash.h"

/***********************************************************
*************************micro define***********************
***********************************************************/
#define TOS_WIFI_IP4ADDR_STRLEN_MAX  16
typedef struct _tag_sta_ip_info {
    UCHAR_T ip[TOS_WIFI_IP4ADDR_STRLEN_MAX];
    UCHAR_T gw[TOS_WIFI_IP4ADDR_STRLEN_MAX];
    UCHAR_T netmask[TOS_WIFI_IP4ADDR_STRLEN_MAX];
} sta_ip_info_t;

/***********************************************************
*************************variable define********************
***********************************************************/

STATIC WF_WK_MD_E wf_mode = WWM_STATION;    /* default set wifi null mode */

STATIC WF_STATION_STAT_E sta_statu = WSS_IDLE;

STATIC sta_ip_info_t sta_ip_info={
        .ip = "0.0.0.0",
        .gw = "0.0.0.0",
        .netmask = "0.0.0.0"
};

STATIC BULL_WIFI_REG_T wifi_reg_ctx;

static const char* WIFI_TAG = "wifi_drv";

static EventGroupHandle_t s_wifi_event_group;
static const int CONNECTED_BIT = BIT0;
static const int DISCONNECTED_BIT = BIT1;
static const int ONNECTING_BIT = BIT2;

/***********************************************************
*************************function define********************
***********************************************************/

/**
 * @brief 事件推送
 * 
 * @param event_id 
 * @param param 
 */
static void wifi_event_send( UINT_T event_id, PVOID_T param )
{
    if( wifi_reg_ctx.event_cb != NULL ){

        wifi_reg_ctx.event_cb( event_id, NULL );
    }
}

static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    ESP_LOGW( WIFI_TAG,"event_id:%ld ",event_id);
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        ESP_LOGW( WIFI_TAG,"WIFI Started");
        // esp_wifi_connect();
        wifi_event_send( BULL_WIFI_EVENT_START, NULL);
        
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        ESP_LOGW( WIFI_TAG, "WIFI Disconnect");

        sta_statu = WSS_CONN_FAIL;

        wifi_event_send( BULL_WIFI_EVENT_DISCONN, NULL);

        xEventGroupClearBits(s_wifi_event_group, ONNECTING_BIT);
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
        xEventGroupSetBits(s_wifi_event_group, DISCONNECTED_BIT);
        
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGW( WIFI_TAG, "Got IP:" IPSTR, IP2STR(&event->ip_info.ip));

        sta_statu = WSS_CONN_SUCCESS;

        esp_ip4addr_ntoa( &event->ip_info.ip,sta_ip_info.ip, TOS_WIFI_IP4ADDR_STRLEN_MAX );
        esp_ip4addr_ntoa( &event->ip_info.gw,sta_ip_info.gw, TOS_WIFI_IP4ADDR_STRLEN_MAX );
        esp_ip4addr_ntoa( &event->ip_info.netmask,sta_ip_info.netmask, TOS_WIFI_IP4ADDR_STRLEN_MAX );

        sta_statu = WSS_GOT_IP;
        wifi_event_send( BULL_WIFI_EVENT_GOT_IP, NULL);

    }else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED){
        ESP_LOGW( WIFI_TAG,"WIFI connected");
        xEventGroupClearBits(s_wifi_event_group, ONNECTING_BIT);
        xEventGroupClearBits(s_wifi_event_group, DISCONNECTED_BIT);
        xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
        wifi_event_send( BULL_WIFI_EVENT_CONNECTED, NULL);
    }
}

/**
 * @brief scan current environment and obtain all the ap
 *        infos in current environment
 * 
 * @param[out]      ap_ary      current ap info array
 * @param[out]      num         the num of ar_ary
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_all_ap_scan(AP_IF_S **ap_ary, uint16_t *num)
{
    if(NULL == ap_ary || NULL == num) {
        return OPRT_INVALID_PARM;
    }
	
	OPERATE_RET op_ret = OPRT_OS_ADAPTER_OK;
    esp_err_t esp_ret = ESP_OK;
	
	wifi_scan_config_t scan_config = {
        .scan_type = WIFI_SCAN_TYPE_ACTIVE,
    };

    esp_ret = esp_wifi_scan_start(&scan_config,true);
    if(ESP_OK != esp_ret) {
        ESP_LOGI( WIFI_TAG,"esp_wifi_scan_start fail:%d", esp_ret);
		return OPRT_WF_AP_SACN_FAIL;
	}

    USHORT_T apnum = 0;
    esp_ret = esp_wifi_scan_get_ap_num(&apnum);
    if(ESP_OK != esp_ret)
	{
        ESP_LOGI( WIFI_TAG,"esp_wifi_scan_get_ap_num fail:%d", esp_ret);
		return OPRT_WF_AP_SACN_FAIL;
	}

    wifi_ap_record_t *aprecords = (wifi_ap_record_t*)bull_hal_sys_memory_malloc(apnum*sizeof(wifi_ap_record_t));
	if (NULL == aprecords) {
        ESP_LOGI( WIFI_TAG,"Malloc_error.");
        return OPRT_MALLOC_FAILED;
    }

    if (ESP_OK != esp_wifi_scan_get_ap_records(&apnum, aprecords)) {
        bull_hal_sys_memory_free(aprecords);
        return OPRT_WF_AP_SACN_FAIL;
    }

    AP_IF_S* ap_group = (AP_IF_S*)bull_hal_sys_memory_malloc(SIZEOF(AP_IF_S) * apnum);
    if (NULL == ap_group) {
        ESP_LOGI( WIFI_TAG,"Malloc_error.");
        bull_hal_sys_memory_free(aprecords);
        return OPRT_MALLOC_FAILED;
    }
	
    for(int i = 0;i < apnum;i++){
		ap_group[i].channel = (BYTE_T)aprecords[i].primary;
		ap_group[i].rssi = (SCHAR_T)aprecords[i].rssi;
		ap_group[i].bssid[0] = (BYTE_T)aprecords[i].bssid[0];
		ap_group[i].bssid[1] = (BYTE_T)aprecords[i].bssid[1];
		ap_group[i].bssid[2] = (BYTE_T)aprecords[i].bssid[2];
		ap_group[i].bssid[3] = (BYTE_T)aprecords[i].bssid[3];
		ap_group[i].bssid[4] = (BYTE_T)aprecords[i].bssid[4];
		ap_group[i].bssid[5] = (BYTE_T)aprecords[i].bssid[5];
		strncpy((CHAR_T*)ap_group[i].ssid,(CHAR_T*)aprecords[i].ssid, WIFI_SSID_LEN+1);
		ap_group[i].s_len = (BYTE_T)strlen((CHAR_T*)aprecords[i].ssid);
    }
	
	*ap_ary = ap_group;

	*num = apnum;

    bull_hal_sys_memory_free(aprecords);

    return op_ret;
}

/*
 * @param[in]       ssid        the specific ssid
 * @param[out]      ap          the ap info
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_assign_ap_scan(const signed char *ssid, AP_IF_S **ap)
{
    if(NULL == ssid || NULL == ap) {
        return OPRT_INVALID_PARM;
    }

    OPERATE_RET op_ret = OPRT_OS_ADAPTER_OK;
	
	
	wifi_scan_config_t scan_config = {
        .scan_type = WIFI_SCAN_TYPE_ACTIVE,
    };

    op_ret = esp_wifi_scan_start(&scan_config,true);
    if(ESP_OK != op_ret) {
        ESP_LOGI( WIFI_TAG,"esp_wifi_scan_start fail:%d", op_ret);
		op_ret = OPRT_WF_AP_SACN_FAIL;
		return op_ret;
	}

    USHORT_T apnum = 0;
    if(ESP_OK != esp_wifi_scan_get_ap_num(&apnum)) {
        ESP_LOGI( WIFI_TAG,"esp_wifi_scan_get_ap_num fail");
		op_ret = OPRT_WF_AP_SACN_FAIL;
		return op_ret;
	}

    wifi_ap_record_t *aprecords = (wifi_ap_record_t*)malloc(apnum*sizeof(wifi_ap_record_t));
	if (NULL == aprecords) {
        ESP_LOGI( WIFI_TAG,"Malloc_error.");
        return OPRT_MALLOC_FAILED;
    }

    if (ESP_OK != esp_wifi_scan_get_ap_records(&apnum, aprecords)) {
        ESP_LOGI( WIFI_TAG,"esp_wifi_scan_get_ap_records fail");
        op_ret = OPRT_WF_AP_SACN_FAIL;
        free(aprecords);
        return op_ret;
    }

    AP_IF_S* ap_single = (AP_IF_S*)malloc(SIZEOF(AP_IF_S));
    if(NULL == ap_single) {
        ESP_LOGI( WIFI_TAG,"Malloc_error.");
        free(aprecords);
        return OPRT_MALLOC_FAILED;
    }

    INT_T i;
    for (i = 0; i < apnum; i++) {
        if (strcmp((CHAR_T*)ssid, (CHAR_T*)aprecords[i].ssid) == 0) {
            ap_single->channel = (BYTE_T)aprecords[i].primary;
            ap_single->rssi = (SCHAR_T)aprecords[i].rssi;
            ap_single->bssid[0] = (BYTE_T)aprecords[i].bssid[0];
            ap_single->bssid[1] = (BYTE_T)aprecords[i].bssid[1];
            ap_single->bssid[2] = (BYTE_T)aprecords[i].bssid[2];
            ap_single->bssid[3] = (BYTE_T)aprecords[i].bssid[3];
            ap_single->bssid[4] = (BYTE_T)aprecords[i].bssid[4];
            ap_single->bssid[5] = (BYTE_T)aprecords[i].bssid[5];
            strncpy((CHAR_T*)ap_single->ssid, (CHAR_T*)aprecords[i].ssid, WIFI_SSID_LEN+1);
            ap_single->s_len = (BYTE_T)strlen(aprecords[i].ssid);
            break;
        }
    }
    //not find
    if (i == apnum) {
        op_ret = OPRT_WF_NOT_FIND_ASS_AP;
    } else {
        *ap = ap_single;
        op_ret = OPRT_OS_ADAPTER_OK;
    }

    free(aprecords);
	
    return op_ret;
}


/**
 * @brief set wifi interface work channel
 * 
 * @param[in]       chan        the channel to set
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_set_cur_channel(const unsigned char chan)
{
    INT_T ret = 0;
    ret = esp_wifi_set_channel(chan,WIFI_SECOND_CHAN_NONE);
    if(ret != ESP_OK) {
        return OPRT_OS_ADAPTER_COM_ERROR;
    }

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief get wifi interface work channel
 * 
 * @param[out]      chan        the channel wifi works
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_get_cur_channel(uint8_t *chan)
{
    INT_T ret = 0;
	
	wifi_second_chan_t second_chan;
	UCHAR_T primary_chan;
	
    ret = esp_wifi_get_channel(&primary_chan,&second_chan);
    if(ret != ESP_OK) {
        return OPRT_OS_ADAPTER_COM_ERROR;
    }

    *chan = primary_chan;

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief get wifi work mode
 * 
 * @param[out]      mode        wifi work mode
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_get_work_mode(WF_WK_MD_E *mode)
{
    wifi_mode_t wifi_mode = WIFI_MODE_NULL;
    esp_err_t ret = esp_wifi_get_mode(&wifi_mode);
    if (ESP_OK != ret) {
        ESP_LOGI( WIFI_TAG,"esp_wifi_get_mode err:%x", ret);
        return OPRT_OS_ADAPTER_COM_ERROR;
    }
    *mode = WWM_LOWPOWER;

    switch(wifi_mode)
    {
        case WIFI_MODE_AP:
            *mode = WWM_SOFTAP;
            break;
        case WIFI_MODE_APSTA:
            *mode = WWM_STATIONAP;
            break;
        case WIFI_MODE_STA:
            *mode = WWM_STATION;
            break;
        default:
            *mode = WWM_LOWPOWER;
            break;
    }
    
    if(wf_mode == WWM_SNIFFER)
    {
        *mode = WWM_SNIFFER; // 在sniffer模式下，返回的可能是station，故此处需要判断
    }
    if (*mode != wf_mode) {
        ESP_LOGI( WIFI_TAG,"get mode:%d,cache mode:%d!!!", *mode, wf_mode);
    }
    *mode = wf_mode;

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief get wifi ip info.when wifi works in
 *        ap+station mode, wifi has two ips.
 * 
 * @param[in]       wf          wifi function type
 * @param[out]      ip          the ip addr info
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_get_ip(const WF_IF_E wf, NW_IP_S *ip)
{
    if (NULL == ip) {
        return OPRT_INVALID_PARM;
    }

    WF_WK_MD_E mode = 0;
    bull_hal_drv_wifi_get_work_mode(&mode);
    if ((WF_STATION == wf) && (mode != WWM_STATION && mode != WWM_STATIONAP)) {
        return OPRT_OS_ADAPTER_COM_ERROR;
    } else if ((WF_AP == wf) && (mode != WWM_SOFTAP && mode != WWM_STATIONAP)) {
        return OPRT_OS_ADAPTER_COM_ERROR;
    }

    if (mode == WWM_STATION && sta_statu != WSS_GOT_IP) {
        ESP_LOGI( WIFI_TAG,"station mode do't get ip");
        return OPRT_OS_ADAPTER_COM_ERROR;
    }
    if (!strncmp(sta_ip_info.ip, "0.0.0.0", TOS_WIFI_IP4ADDR_STRLEN_MAX)) {
        ESP_LOGI( WIFI_TAG,"ip addr is 0.0.0.0!!!");
        return OPRT_OS_ADAPTER_COM_ERROR;
    }

    strncpy(ip->ip, sta_ip_info.ip, TOS_WIFI_IP4ADDR_STRLEN_MAX);
    strncpy(ip->gw, sta_ip_info.gw, TOS_WIFI_IP4ADDR_STRLEN_MAX);
    strncpy(ip->mask, sta_ip_info.netmask, TOS_WIFI_IP4ADDR_STRLEN_MAX);
    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief get wifi mac info.when wifi works in
 *        ap+station mode, wifi has two macs.
 * 
 * @param[in]       wf          wifi function type
 * @param[out]      mac         the mac info
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_get_mac(const WF_IF_E wf, NW_MAC_S *mac)
{
    esp_err_t ret = 0;
    if (wf == WF_AP) {
        ret = esp_wifi_get_mac(ESP_IF_WIFI_AP, mac->mac);
    } else if (wf == WF_STATION) {
        ret = esp_wifi_get_mac(ESP_IF_WIFI_STA, mac->mac);
    }

    if (ret != ESP_OK) {
        ESP_LOGI( WIFI_TAG,"wifi_get_mac_address ret:%d\n", ret);
        return OPRT_OS_ADAPTER_COM_ERROR;
    }

    ESP_LOGI( WIFI_TAG,"read wifi mac:" MACSTR "\r\n", MAC2STR(mac->mac));

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief 获取当前wifi ssid和passwd
 * 
 * @param interface 
 * @param ssid 
 * @param passwd 
 * @return int 
 */
int bull_hal_drv_wifi_get_ssid_password ( bull_wifi_interface_t interface, OUT char *ssid, OUT char *passwd )
{
    int ret = -1;

    wifi_config_t conf = { 0 };

    if( ESP_OK == esp_wifi_get_config( interface, &conf ) ){

        ESP_LOGI( WIFI_TAG,"ssid:%s ps:%s", conf.sta.ssid, conf.sta.password );
        strncpy( ssid, conf.sta.ssid, strlen( conf.sta.ssid ) );
        strncpy( passwd, conf.sta.password, strlen( conf.sta.password ) );
        ret = 0;
    }
    
    return ret;
}


/**
 * @brief set wifi mac info.when wifi works in
 *        ap+station mode, wifi has two macs.
 * 
 * @param[in]       wf          wifi function type
 * @param[in]       mac         the mac info
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_set_mac(const WF_IF_E wf, const NW_MAC_S *mac)
{
    ESP_LOGI( WIFI_TAG,"write wifi mac:"MACSTR"\r\n",MAC2STR(mac->mac));

    esp_err_t ret = 0;
	
	if(wf == WF_AP)
	{
		ret = esp_wifi_set_mac(ESP_IF_WIFI_AP, mac->mac);
	}
	else if(wf == WF_STATION)
	{
		ret = esp_wifi_set_mac(ESP_IF_WIFI_STA, mac->mac);
	}
    
    if(ret != ESP_OK) {
        ESP_LOGI( WIFI_TAG,"wifi_set_mac_address ret：%d",ret);
        return OPRT_OS_ADAPTER_COM_ERROR;
    }

    return OPRT_OS_ADAPTER_OK;
}


/**
 * @brief 重置wifi协议栈
 * 
 * @return int 
 */
int bull_hal_drv_wifi_restore(void)
{
    return esp_wifi_restore();
}


/**
 * @brief connect wifi with ssid and passwd
 * 
 * @param[in]       ssid
 * @param[in]       passwd
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
// only support wap/wap2 
int bull_hal_drv_wifi_station_connect(const char *ssid, const char *passwd)
{
    static bool connect_flag = false;

    if ( connect_flag ){

        return OPRT_OS_ADAPTER_NETWORK_ERROR;
    }
    
    connect_flag = true;

    ESP_LOGW( WIFI_TAG,"esp_wifi_connect ssid:%s,pwd:%s",ssid, passwd);

    int bits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ONNECTING_BIT, 0, 1, 0);

    // ESP_LOGE( WIFI_TAG,"bits ssid:%d",bits);
    wifi_config_t wifi_config = {
        .sta = {
            .scan_method = WIFI_ALL_CHANNEL_SCAN,
        },
    };

    strncpy((CHAR_T*)wifi_config.sta.ssid, ssid, strlen(ssid));
    strncpy((CHAR_T*)wifi_config.sta.password, passwd, strlen(passwd));

    // ESP_LOGW( WIFI_TAG,"esp_wifi_connect ssid:%s,pwd:%s", wifi_config.sta.ssid, wifi_config.sta.password);
    // ESP_LOGW( WIFI_TAG,"bits & CONNECTED_BIT:%d ",bits  );

    // if (bits & CONNECTED_BIT || bits & ONNECTING_BIT ) {
        // ESP_LOGW( WIFI_TAG,"PASS "  );
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
        xEventGroupClearBits(s_wifi_event_group, DISCONNECTED_BIT);
        // ESP_ERROR_CHECK( esp_wifi_disconnect() );
        esp_wifi_disconnect();
        xEventGroupWaitBits(s_wifi_event_group, DISCONNECTED_BIT, 0, 1, 300);  //Set timeout 3S
    // }

    xEventGroupSetBits(s_wifi_event_group, ONNECTING_BIT);

    // EventBits_t ret2 = xEventGroupWaitBits(s_wifi_event_group, ONNECTING_BIT, 0, 1, 10);
    // ESP_LOGW( WIFI_TAG,"ONNECTING_BIT:%ld", ret2 );

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    // ESP_ERROR_CHECK(esp_wifi_connect());
    esp_err_t ret1 = esp_wifi_connect();

    if (ret1 != ESP_OK) {
        ESP_LOGE(WIFI_TAG, "esp_wifi_connect fail, ret is %d", ret1);
       
    }
    

    EventBits_t ret = xEventGroupWaitBits(s_wifi_event_group, ONNECTING_BIT, pdFALSE, pdTRUE, 10);

    connect_flag = false;
    // ESP_LOGW( WIFI_TAG,"CONNECTED_BIT:%ld", ret );
    return OPRT_OS_ADAPTER_OK;
}


/**
 * @brief 断开wifi连接
 * 
 * @return int 
 */
int bull_hal_drv_wifi_station_disconnect(void)
{
    esp_err_t ret = 0;
    ret = esp_wifi_disconnect();
    if(ret != ESP_OK) {
        ESP_LOGI( WIFI_TAG,"esp_wifi_disconnect err:%x",ret);
        return OPRT_OS_ADAPTER_COM_ERROR;
    }
    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief get wifi connect rssi
 * 
 * @param[out]      rssi        the return rssi
 * @return  OPRT_OS_ADAPTER_OK: success  Other: fail
 */
int bull_hal_drv_wifi_station_get_conn_ap_rssi(signed char *rssi)
{
    esp_err_t ret = 0;
	wifi_ap_record_t ap_info;
	
	ret = esp_wifi_sta_get_ap_info(&ap_info);
    if(ret != ESP_OK) {
        ESP_LOGI( WIFI_TAG,"esp_wifi_sta_get_ap_info_err:%x", ret);
        return OPRT_OS_ADAPTER_COM_ERROR;
    }

    *rssi = ap_info.rssi;
    return OPRT_OS_ADAPTER_OK;
}



/**
 * @brief 初始化wifi
 * 
 * @param ctx 注册到wifi上的回调函数结构体
 * @return int 
 */
int bull_hal_drv_wifi_init(BULL_WIFI_REG_T *ctx)
{

    static bool initialized = false;

    if (initialized) {
        return OPRT_INIT_MORE_THAN_ONCE;
    }

    if ( ctx ){

        memcpy(&wifi_reg_ctx,ctx,sizeof(BULL_WIFI_REG_T));
        ESP_LOGW( WIFI_TAG,"bull_hal_drv_wifi_init");
    }
    
    nvs_flash_init();

    s_wifi_event_group = xEventGroupCreate();

    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *esp_netif = esp_netif_create_default_wifi_sta();

    if(NULL != ctx->param && ctx->evt_id_wifi_host_name && esp_netif){
        esp_netif_set_hostname(esp_netif, ctx->param);
        // const char *hostname;
        // esp_netif_get_hostname(esp_netif, &hostname);
        // ESP_LOGW( WIFI_TAG,"%s hostname=%s",hostname_dn, hostname);
        
    }

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); // wifi 不休眠

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
                                                        
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    ESP_ERROR_CHECK(esp_wifi_start());

    initialized = true;

    return OPRT_OK;
}
